package org.bukkit.pm.arena;

import it.patamau.bukkit.GenericPlugin;

import java.io.File;
import java.util.Random;
import java.util.logging.Level;

import org.bukkit.ChatColor;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.Event.Priority;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.PluginLoader;
import org.bukkit.plugin.PluginManager;

public class ArenaPlugin extends GenericPlugin {
	
	public static final String 
		KEY_SIZE = "arena.size",
		KEY_OFFSETX = "arena.offsetx",
		KEY_OFFSETY = "arena.offsety";
	public static final int DEF_SIZE = 256; //from -128 to +128
	public static final int DEF_OFFSET = DEF_SIZE/2+24;
	
	private int _offsetx, _offsety;
	private int _size; //the arena side length in blocks (arena is squared)
	private int _min, _max; //precalculatd coordinates
	
	private final ArenaPlayerListener _arenaPlayerListener = new ArenaPlayerListener(this);
	private final ArenaVehicleListener _arenaVehicleListener = new ArenaVehicleListener(this);
	
	private Random _random = new Random();

	public ArenaPlugin(PluginLoader pluginLoader, Server instance,
			PluginDescriptionFile desc, File folder, File plugin,
			ClassLoader cLoader) {
		super(pluginLoader, instance, desc, folder, plugin, cLoader);
		_random.setSeed(System.currentTimeMillis());
	}
	
	public void onEnable() {
		init();
		_size = getProperty(KEY_SIZE,DEF_SIZE);
		_offsetx = getProperty(KEY_OFFSETX, DEF_OFFSET);
		_offsety = getProperty(KEY_OFFSETY, DEF_OFFSET);
		_max = _size/2;
		_min = -_max;
		
		PluginManager pm = this.getServer().getPluginManager();
		pm.registerEvent(Event.Type.VEHICLE_MOVE, _arenaVehicleListener, Priority.Lowest, this);
		pm.registerEvent(Event.Type.PLAYER_MOVE, _arenaPlayerListener, Priority.Lowest, this);
		pm.registerEvent(Event.Type.PLAYER_JOIN, _arenaPlayerListener, Priority.Normal, this);
		pm.registerEvent(Event.Type.PLAYER_TELEPORT, _arenaPlayerListener, Priority.Lowest, this);
		pm.registerEvent(Event.Type.PLAYER_COMMAND, _arenaPlayerListener, Priority.Normal, this);
	}

	public void onDisable() {
		close();
	}
	
	public void forceBack(Player p){
		p.teleportTo(getSpawnLocation(p));
		p.sendMessage(ChatColor.RED+"You've been teleported back to the arena!");
	}
	
	public Location getSpawnLocation(Player player) {
		int rx, rz, ry;
		do{
			rx = _random.nextInt(_size)-_max+_offsetx;
			rz = _random.nextInt(_size)-_max+_offsety;
			//force loading destination chunk
			Chunk c = player.getWorld().getChunkAt(rx, rz);
			if(!player.getWorld().isChunkLoaded(c)){
				player.getWorld().loadChunk(c);
			}
			ry = player.getWorld().getHighestBlockYAt(rx, rz);
			//print warning message if no block can be found in this chunk
			if(ry==0){
				log(Level.WARNING,"unable to find a good spawn block at ("+rx+","+rz+"): trying again...");
			}
			//XXX: there is no reason to manually quit the loop, as a good location will be found for sure
		}while(ry==0);		
		Block b = player.getWorld().getBlockAt(rx,ry,rz);
		log(Level.INFO,"random spawn found at ("+rx+","+ry+","+rz+")");
		//return the block location
		return b.getLocation();
	}
	
	public void printWarning(Player p){
		p.sendMessage(ChatColor.RED+"You've reached the arena limit");
	}

	/**
	 * Verify player is in or out
	 * @param p
	 * @return true if it is in, false if it stepped out
	 */
	public boolean checkBounds(Player p) {
		Location l = p.getLocation();
		int x = l.getBlockX()-_offsetx;
		int z = l.getBlockZ()-_offsety;
		if(x<_min||x>_max||z<_min||z>_max){
			return false;
		}else{
			return true;
		}
	}


}
